use std::sync::{
	atomic::{AtomicU16, Ordering},
	LazyLock,
};

use time::format_description;
use tools::{
	global_defin::global::{format_date_time, DEFAULT_DATA_FORMAT},
	utils::{current_data_time_with_zone, gen_id::gen_md5_supp, http::send_post_request},
	ResultEx,
};
use tracing::debug;

use crate::{config::platform_id, db::persistence::InboundDBO};

use super::inbound400::context::InboundRunContext;

///来电名片功能的配置信息
#[derive(Debug)]
pub struct CallingCardConf {
	pub key: String,
	pub url: String,
	pub mp_info_name: String,
}

impl CallingCardConf {
	pub fn new(key: String, url: String, mp_info_name: String) -> Self {
		CallingCardConf {
			key,
			url,
			mp_info_name,
		}
	}

	///向上海电信发送来电名片..目前此功能仅一个参数.
	/// 将400号码向其发送出去
	pub async fn send_request_shtel(
		&self,
		context: &InboundRunContext,
		called: &str,
	) -> ResultEx<(String, String)> {
		debug!("开始发送来电名片,配置:{self:?}");

		let billing_id = self.gen_billing_id();
		let fnum_name = InboundDBO::get_calling_fnum_name(context).await?;
		let now_data = format!(
			"{}{}{}",
			&context.caller_num(),
			called,
			format_date_time(&current_data_time_with_zone(), &DEFAULT_DATA_FORMAT)
		);
		let token = gen_md5_supp(&now_data);
		let body = format!(
			r#"{{"billingId":"{}","callInNumber":"{}","callOutNumber":"{}","shortSms":"0","mpInfo":"{}&&{}({})","token":"{}"}}"#,
			&billing_id,
			&context.caller_num(),
			called,
			&self.mp_info_name,
			fnum_name,
			&context.external_num,
			&token
		);

		let mut res = send_post_request(&self.url, body).await?;
		let rcode = res.remove("rcode");
		match rcode {
			Some(serde_json::Value::String(code)) => Ok((billing_id, code)),
			_ => Ok((billing_id, String::default())),
		}
	}

	///生成消息体的billingID.目前此方法对应上海电信的接口要求
	#[inline]
	fn gen_billing_id(&self) -> String {
		format!(
			"{}{}{}{}",
			&self.key,
			format_date_time(&current_data_time_with_zone(), &DATA_FORMAT),
			platform_id(),
			ID.fetch_add(1, Ordering::Relaxed)
		)
	}
}

static ID: AtomicU16 = AtomicU16::new(0);
static DATA_FORMAT: LazyLock<Vec<format_description::FormatItem<'_>>> =
	LazyLock::new(|| format_description::parse("[year][month][day][hour][minute][second]").unwrap());
